package com.danbay.cloud.lock.device.service;

import com.danbay.cloud.lock.device.api.dto.*;
import com.danbay.cloud.lock.device.api.service.IDeviceInfoReportDataService;
import com.danbay.cloud.lock.device.client.DeviceAccessClient;
import com.danbay.cloud.lock.device.constant.LockConstant;
import com.danbay.cloud.lock.device.constant.LockPwdConstant;
import com.danbay.cloud.lock.device.constant.LockPwdType;
import com.danbay.cloud.lock.device.constant.MessageInfoConstant;
import com.danbay.cloud.lock.device.entity.*;
import com.danbay.cloud.lock.device.mapper.*;
import com.danbay.cloud.lock.device.util.CollectionUtils;
import com.danbay.cloud.lock.device.util.LockCommonUtils;
import com.danbay.framework.exception.BusinessException;
import com.danbay.framework.utils.DateUtils;
import com.danbay.framework.utils.StringUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author yangyanchen on 2017/12/18
 *         Copyright © 2016 －2017 旦倍科技
 */
@Slf4j
@Service
public class DeviceInfoReportDataService implements IDeviceInfoReportDataService {

    @Autowired
    private LockPrePasswordService lockPrePasswordService;

    @Autowired
    private DeviceInfoCacheService deviceInfoCacheService;

    @Autowired
    private DeviceAccessClient deviceAccessClient;

    @Autowired
    private DeviceInfoMapper deviceInfoMapper;

    @Autowired
    private LogInfoMapper logInfoMapper;

    @Autowired
    private DevicePwdInfoMapper devicePwdInfoMapper;

    @Autowired
    private LockPrePasswordMapper lockPrePasswordMapper;

    @Autowired
    private MessageInfoMapper messageInfoMapper;

    @Autowired
    private OperationDetailMapper operationDetailMapper;

    /**
     * 门锁的开门记录上报
     * @param openDoorReportDto 数据包
     * @throws BusinessException
     */
    @Override
    public void openDoorReport(OpenDoorReportDto openDoorReportDto) throws BusinessException {
        DeviceInfo deviceInfo = deviceInfoMapper.selectOne(DeviceInfo.builder()
                            .deviceId(openDoorReportDto.getDeviceId()).build());
        if (null == deviceInfo){
            throw new  BusinessException("设备:"+openDoorReportDto.getDeviceId()+"不存在");
        }
        if (StringUtils.isNotEmpty(openDoorReportDto.getTime())){
            deviceInfo.setUser_lastopenlocktime(DateUtils.parse(openDoorReportDto.getTime(),"yyMMddHHmmss").toDate());
        }
        if (null != openDoorReportDto.getVoltage() && openDoorReportDto.getVoltage() > 0){
            deviceInfo.setDeviceElectricity(LockCommonUtils.getLockElectricity(openDoorReportDto.getVoltage()));
        }
        deviceInfoMapper.updateById(deviceInfo);
        LogInfo logInfo = LogInfo.builder().deviceInfo(deviceInfo.getId())
                                           .deviceLogType("2")
                                           .operatorType(String.valueOf(openDoorReportDto.getType()))
                                           .platform("Web端")
                                           .type("1")
                                           .content(LockPwdConstant.DEVICE_LOCK_PWD_TYPE_MAP.get(openDoorReportDto.getType())+"开门")
                                           .operatorTime(new Date())
                                           .operatorAddress("")
                                           .operatorPwd(openDoorReportDto.getAlias())
                                           .deviceType("0")
                                           .hasDelete("0")
                                           .deviceId(deviceInfo.getDeviceId())
                                           .build();
        logInfoMapper.insert(logInfo);
    }

    /**
     * 门锁的报警记录上报
     * @param warningReportDto
     * @throws BusinessException
     */
    @Override
    public void warningReport(WarningReportDto warningReportDto) throws BusinessException {
        DeviceInfo deviceInfo = deviceInfoMapper.selectOne(DeviceInfo.builder().deviceId(warningReportDto.getDeviceId()).build());
        if (null == deviceInfo){
            throw new BusinessException("查找不到设备ID");
        }
        String titile = MessageInfoConstant.WARNINIG_MAP.get(warningReportDto.getCode());
        MessageInfo messageInfo = MessageInfo.builder()
                                       .deviceInfo(deviceInfo.getId())
                                       .type(MessageInfoConstant.MESSAGE_TYPE_SECURITY)
                                       .createTime(new Date())
                                       .titile(titile)
                                       .readNum(0L)
                                       .content(messageContent(titile,deviceInfo.getDeviceId()))
                                       .build();
        String operatorType = "";
        switch (warningReportDto.getCode()){
            case 1:
                messageInfo.setContent("设备"+deviceInfo.getDeviceId()+"密码输入错误5次，请确认是否有安全事件");

                operatorType = MessageInfoConstant.KEY_PASSWORD_ERROR;
                break;
            case 2:
                operatorType = MessageInfoConstant.KEY_LOWELE_WARN;
                deviceInfo.setStatus(LockConstant.DEVICE_STATUS_LOWELE);
                deviceInfo.setDeviceElectricity(LockConstant.DEVICE_LOCK_LOW_ELETRIC);
                messageInfo.setType(MessageInfoConstant.MESSAGE_TYPE_EXCEPTION);
                deviceInfoMapper.updateById(deviceInfo);
                break;
            case 3:
                operatorType = MessageInfoConstant.KEY_DESTORY_WARN;
                break;
            case 4:
                operatorType = MessageInfoConstant.KEY_DESTORY_WARN;
                break;
            case 5:
                break;
            default:return;
        }
        messageInfoMapper.insert(messageInfo);
        LogInfo logInfo = LogInfo.builder()
                .content("设备"+MessageInfoConstant.WARNINIG_MAP.get(warningReportDto.getCode()))
                .operatorTime(new Date())
                .deviceInfo(deviceInfo.getId())
                .deviceId(deviceInfo.getDeviceId())
                .type(MessageInfoConstant.LOG_TYPE_DEVICE)
                .operatorType(operatorType)
                .deviceLogType(MessageInfoConstant.LOG_TYPE_DEVICE_EXECEPTION)
                .build();
        logInfoMapper.insert(logInfo);
    }

    /**
     * 门锁的权限动态上报:
     *    关于如何实现事务一致性说明: 1.实现的Redis缓存含有数据内容,这里还是要解数据包.
     *                             2.解数据包.根据数据包内容对应获取操作对象.
     *                             3.增加定时任务内容,内容对象包含所有的门锁下发指令.触发时间如何定义
     *                             4.根据6小时一次的密码别名更新的定时任务触发
     *   权限动态并不是代表操作指令完整实现的唯一定义,如下发密码.不会权限动态,但是密码别名列表却有记录.
     * 判定门锁操作指令是否成功是一系列组合动作.起点A:操作指令回复:ACK,中控接收到指令.
     *                                        B:三分钟内门锁回复权限动态,操作指令结束.
     *                                        C:三分钟没有回复权限动态,下发获取别名列表指令.
     *                                        D:别名列表指令没有含有该密码别名,操作指令失败.判断是否重新下发,回到A点且打点1次(3次后终止操作).
     *                                        E:别名列表含有该密码别名,操作指令成功.
     * 也就是说保证事务一致性不是根据messageId,这里代表是保证门锁的远程密码准确可用的.则一定要解数据包.
     * @param accessReportDto
     * @throws BusinessException
     */
    @Override
    public void accessReport(AccessReportDto accessReportDto) throws BusinessException {
        DeviceInfo deviceInfo = deviceInfoMapper.selectOne(DeviceInfo.builder().deviceId(accessReportDto.getDeviceId()).build());
        if (null == deviceInfo){
            throw new BusinessException("设备ID不存在");
        }
        //1.解析操作类型
        switch (accessReportDto.getAction()){
            case 0:
                //0x00 恢复默认值（若是管理员密码恢复默认值，则代表门锁恢复出厂设置）
                dealResetAccess(accessReportDto);
                break;
            case 1:
                //0x01 新增
                dealNewPwdAccess(accessReportDto,deviceInfo);
                break;
            case 2:
                //0x02 修改
                dealEditPwdAccess(accessReportDto);
                break;
            case 3:
                //0x03 删除
                dealDelPwdAccess(accessReportDto);
                break;
            case 4:
                //0x04 暂停
                dealPausePwdAccess(accessReportDto);
                break;
            case 5:
                dealPausePwdAccess(accessReportDto);
                //解除暂停
                break;
            case 6:
                //直接清空用户密码
                devicePwdInfoMapper.deleteRecordsByDeviceIdAndPwdType(accessReportDto.getDeviceId(),String.valueOf(accessReportDto.getType()));
                //0x06 清空密码（清空用户密码使用）
                break;
            case 7:
                //0x07 复位密码（复位管家密码时使用）
                //复位管家密码,如果能获取到管家密码信息,则将管家密码内容置空,获取不到则不进行处理
                devicePwdInfoMapper.updateRecordsByDeviceIdAndPwdAlias(accessReportDto.getDeviceId(),
                        accessReportDto.getAlias(),String.valueOf(accessReportDto.getType()));
                break;
            default:return;
        }
    }

//    @Override
//    public void tongueReport() throws BusinessException {
//        //LK-04门锁暂无锁舌上报
//    }

    /**
     * 门锁的定期数据上报
     * @param dataSyncReportDto
     * @throws BusinessException
     */
    @Override
    public void dataSyncReport(DataSyncReportDto dataSyncReportDto) throws BusinessException {
        //1.处理数据
        DeviceInfo deviceInfo = deviceInfoMapper.selectOne(DeviceInfo.builder()
                                        .deviceId(dataSyncReportDto.getDeviceId()).build());
        if(null == deviceInfo) {
            throw new BusinessException("查找不到设备ID");
        }
        deviceInfo.setAdminCount(dataSyncReportDto.getStewardCap());
        deviceInfo.setUserCount(dataSyncReportDto.getUserCap());
        deviceInfo.setTempCount(dataSyncReportDto.getTempCap());
        deviceInfo.setTotalCount(dataSyncReportDto.getTotalCap());
        deviceInfo.setDeviceElectricity(String.valueOf(dataSyncReportDto.getPower()));
        deviceInfo.setHasSync(LockConstant.LOCK_PWD_INFO_HAS_NOT_SYNC);
        deviceInfoMapper.updateById(deviceInfo);
        //2.缓存数据信息
        deviceInfoCacheService.setDataSync(deviceInfo.getDeviceId(),dataSyncReportDto);
        //3.下发获取密码别名命令
        deviceAccessClient.getAlias(dataSyncReportDto.getDeviceId());
    }

    /**
     * 获取门锁的密码别名列表
     * @param aliasDto
     * @throws BusinessException
     */
    @Override
    public void getAlias(AliasDto aliasDto) throws BusinessException {
        DeviceInfo deviceInfo = deviceInfoMapper.selectOne(DeviceInfo.builder()
                                                    .deviceId(aliasDto.getDeviceId()).build());
        if (null == deviceInfo){
            throw new BusinessException("查询设备不存在");
        }
        List<Map<String,String>> aliasList = getAliasRecord(aliasDto);
        if (org.springframework.util.CollectionUtils.isEmpty(aliasList)){
            //获取的密码别名为空,直接拒绝
            return;
        }
        List<DevicePwdInfo> devicePwdInfoList = devicePwdInfoMapper.findByDeviceInfo(deviceInfo.getId());
        final List<LockPrePassword>[] lockPrePasswordList = new List[]{lockPrePasswordMapper.findByDeviceId(aliasDto)};
        List<Map<String,String>> cachePwdList = Lists.newLinkedList();
        cachePwdList = devicePwdInfoList.stream().map(devicePwdInfo -> setPwdAliasMap(devicePwdInfo.getPwdType(),devicePwdInfo.getPwdAlias(),
                String.valueOf(devicePwdInfo.getId()),LockPwdConstant.DEVICE_LOCK_NORMAL_PWD)).collect(Collectors.toList());
        cachePwdList.addAll(lockPrePasswordList[0].stream().map(lockPrePwd ->
                setPwdAliasMap(lockPrePwd.getPsw_type(), lockPrePwd.getPsw_alias(), String.valueOf(lockPrePwd.getId()), LockPwdConstant.DEVICE_LOCK_PRE_PWD)
        ).collect(Collectors.toList()));
        //两个数值比较
        List<Map<String,String>> distinctList = CollectionUtils.getMapDiff(cachePwdList,aliasList,"pwd_alias");
        distinctList.forEach(distinctMap -> {
            int listType = Integer.parseInt(distinctMap.get("list_type"));
            if(listType == Integer.parseInt(LockPwdConstant.DEVICE_LOCK_NORMAL_PWD)){
                devicePwdInfoMapper.deleteById(Long.parseLong(distinctMap.get("id")));
            }
            if (listType == Integer.parseInt(LockPwdConstant.DEVICE_LOCK_PRE_PWD)){
                Long id = Long.parseLong(distinctMap.get("id"));
                lockPrePasswordMapper.deleteById(id);
                //预置密码数据中过滤一条数据
                lockPrePasswordList[0] = lockPrePasswordList[0].stream().filter(lockPrePassword ->
                                                lockPrePassword.getId().intValue() != id.intValue())
                                                    .collect(Collectors.toList());
            }
            if (listType == Integer.parseInt(LockPwdConstant.DEVICE_LOCK_HARD_WARE_PWD)){
                devicePwdInfoMapper.insert(DevicePwdInfo.builder()
                                        .deviceInfo(deviceInfo.getId())
                                        .pwdAlias(distinctMap.get("pwd_alias"))
                                        .pwdType(distinctMap.get("pwd_type"))
                                        .sendCount(10)
                                        .status("0")
                                        .useStatus("1")
                                        .build());
            }
        });
        //因为涉及预置密码删除操作,是不需要查询数据库的,在查询的List里面删除该数据
        if (lockPrePasswordList[0].isEmpty()){
            //保存预置密码记录与下发预置密码
            for (int i = 1; i <= LockPwdType.PRE_LOCK_TEMP_COUNT; i++) {
                lockPrePasswordService.prePassword(deviceInfo.getDeviceId(),LockPwdType.LOCK_PWD_TEMP);
            }
            lockPrePasswordService.prePassword(deviceInfo.getDeviceId(),LockPwdType.LOCK_PWD_MANAGER);
        }else {
            //判断密码数量是否够
            List<LockPrePassword> lockPrePasswords = lockPrePasswordList[0];
            int tempCount = lockPrePasswords.stream().filter(lockPrePassword -> LockPwdType.LOCK_PWD_TEMP.equalsIgnoreCase(
                    lockPrePassword.getPsw_type()
            )).collect(Collectors.toList()).size();
            int userCount = lockPrePasswords.stream().filter(lockPrePassword -> LockPwdType.LOCK_PWD_MANAGER.equalsIgnoreCase(
                    lockPrePassword.getPsw_type()
            )).collect(Collectors.toList()).size();
            if (tempCount < LockPwdType.PRE_LOCK_TEMP_COUNT){
                for (int i = 1; i <= LockPwdType.PRE_LOCK_TEMP_COUNT - tempCount; i++) {
                    lockPrePasswordService.prePassword(deviceInfo.getDeviceId(),LockPwdType.LOCK_PWD_TEMP);
                }
            }
            if (userCount < LockPwdType.PRE_LOCK_ROOMER_COUNT){
                lockPrePasswordService.prePassword(deviceInfo.getDeviceId(),LockPwdType.LOCK_PWD_MANAGER);
            }
        }
    }

    /**
     * 密码别名修改的记录上报
     * @param aliasResultDto
     * @throws BusinessException
     */
    @Override
    public void aliasResultReport(AliasResultDto aliasResultDto) throws BusinessException {
        DeviceInfo deviceInfo = deviceInfoMapper.selectOne(DeviceInfo.builder().deviceId(aliasResultDto.getDeviceId()).build());
        if (null == deviceInfo){
            throw new BusinessException("设备不存在");
        }
        DevicePwdInfo devicePwdInfo = devicePwdInfoMapper.selectOne(DevicePwdInfo.builder()
                                            .deviceInfo(deviceInfo.getId())
                                            .pwdType(String.valueOf(aliasResultDto.getType()))
                                            .pwdAlias(aliasResultDto.getOldAlias()).build());
        if (null == devicePwdInfo){
            throw new BusinessException("查询不到原始密码别名");
        }
        devicePwdInfo.setPwdAlias(aliasResultDto.getNewAlias());
        devicePwdInfoMapper.updateById(devicePwdInfo);
    }

    /**
     * 转换消息内容
     * @param title
     * @param deviceId
     * @return
     */
    private String messageContent(String title, String deviceId) {
        StringBuilder builder = new StringBuilder();
        builder.append("设备ID是:")
               .append(deviceId)
               .append("检测到设备")
               .append(title)
               .append(".");
        return builder.toString();
    }

    /**
     * 转换获取门锁的密码别名上报记录
     * @param aliasDto
     * @return
     */
    private List<Map<String,String>> getAliasRecord(AliasDto aliasDto){
        List<Map<String,String>> list = Lists.newLinkedList();
        for (int i = 0; i < aliasDto.getUser().size(); i++) {
            list.add(setPwdAliasMap(aliasDto.getKind().get(i),aliasDto.getUser().get(i),"0",LockPwdConstant.DEVICE_LOCK_HARD_WARE_PWD));
        }
        return list;
    }

    /**
     * 处理操作类型为复位密码回复的权限动态
     *    备注:这里的处理逻辑,恢复出厂设备之后不能去获取密码别名了，因为密码别名列表被清空!!!
     * @param accessReportDto
     * @throws BusinessException
     */
    private void dealResetAccess(AccessReportDto accessReportDto) throws BusinessException{
        if (Integer.parseInt(LockPwdType.LOCK_PWD_ADMIN) == accessReportDto.getType()){
            //密码类型为管理员密码,则代表门锁恢复出厂设置.
            log.warn("设备门锁:{}恢复出厂设置",accessReportDto.getDeviceId());
            //删除正式密码.
            devicePwdInfoMapper.deleteRecordsByDeviceId(accessReportDto.getDeviceId());
            //删除预置密码
            lockPrePasswordMapper.deleteRecordsByDeviceId(accessReportDto);
            //重新获取密码别名
//            deviceAccessClient.getAlias(accessReportDto.getDeviceId());
        }
    }

    /**
     * 处理新增密码回复的权限动态
     * @param accessReportDto
     */
    private void dealNewPwdAccess(AccessReportDto accessReportDto,DeviceInfo deviceInfo) throws BusinessException {
        //1.取缓存
        LockPrePassword lockPrePassword = deviceInfoCacheService.getLockPrePassword(accessReportDto.getDeviceId(),
                                            accessReportDto.getAlias(),String.valueOf(accessReportDto.getType()));
        if (null == lockPrePassword){
            if (accessReportDto.getOpCode() == 0){
                //修改:可能是避过预置密码直接进行的密码下发.
                DevicePwdInfo devicePwdInfo = devicePwdInfoMapper.findByDeviceIdAndPwdAlias(accessReportDto);
                if (null != devicePwdInfo){
                    devicePwdInfo.setStatus(LockPwdConstant.LOCK_PWD_NORMAL);
                    devicePwdInfoMapper.updateById(devicePwdInfo);
                }else {
                    //取不到预置密码缓存,存在可能性为门锁密码为本地添加的可能,这里直接根据预置密码保存数据即可
                    devicePwdInfoMapper.insert(DevicePwdInfo.builder()
                            .deviceInfo(deviceInfo.getId())
                            .pwdType(String.valueOf(accessReportDto.getType()))
                            .pwdAlias(accessReportDto.getAlias())
                            .status(LockPwdConstant.LOCK_PWD_NORMAL)
                            .createTime(new Date())
                            .type("")
                            .hasSync(LockPwdConstant.LOCK_STATUS_HAS_SYNC)
                            .build());
                }
            }else {
                throw new BusinessException("设备-门锁:" + accessReportDto.getDeviceId() + "出现操作异常");
            }
        }else {
        //根据结果处理预置密码
        switch (accessReportDto.getOpCode()){
            case 0:
                lockPrePassword.setPsw_goal(LockPwdConstant.LOCK_PRE_PASSWORD_EFFECTED);
                lockPrePasswordMapper.updateById(lockPrePassword);
                log.info("操作的门锁设备ID:{}操作成功",accessReportDto.getDeviceId());
                break;
            case 1:
                log.warn("操作的门锁设备ID:{}已存在重复密码",accessReportDto.getDeviceId());
                //删除该门锁预置密码,重新获取密码别名
                lockPrePasswordMapper.deleteById(lockPrePassword.getId());
                deviceAccessClient.getAlias(accessReportDto.getDeviceId());
                break;
            case 2:
                log.warn("操作的门锁设备ID:{}存储空间已满",accessReportDto.getDeviceId());
                //删除该门锁密码,修改门锁的密码存储空间
                lockPrePasswordMapper.deleteById(lockPrePassword.getId());
                break;
            case 3:
                //新增密码不处理这一操作结果
                break;
            case 4:
                log.error("新增门锁密码出现为止错误.");
                break;
            default:return;
            }
        }
    }

    /**
     * 处理修改密码回复的权限动态
     * @param accessReportDto
     * @throws BusinessException
     */
    private void dealEditPwdAccess(AccessReportDto accessReportDto) throws BusinessException{
        //这里不去使用缓存的机制,耦合太深.从数据库中获取密码记录
        DevicePwdInfo devicePwdInfo = devicePwdInfoMapper.findByDeviceIdAndPwdAlias(accessReportDto);
        if (null == devicePwdInfo) {
            //修改门锁密码的权限动态获取不到记录,就是意味着,在新增密码期限内门锁失联,所以获取不到本地新增密码的权限动态上报.
            deviceAccessClient.getAlias(accessReportDto.getDeviceId());
            log.warn("设备-门锁:{}修改密码操作无法进行处理", accessReportDto.getDeviceId());
        } else {
            switch (accessReportDto.getOpCode()) {
                case 0:
                    /**
                     * 批量修改管家密码添加明细
                     */
                    log.info("操作的门锁设备ID:{}操作成功", accessReportDto.getDeviceId());
                    dealHouseKeeperUpdate(devicePwdInfo,accessReportDto);
                    //修改设置密码状态
                    devicePwdInfo.setStatus(LockPwdConstant.LOCK_PWD_NORMAL);
                    devicePwdInfo.setPassword(devicePwdInfo.getWillChangePwd());
                    devicePwdInfo.setHasSync(LockPwdConstant.LOCK_STATUS_HAS_SYNC);
                    devicePwdInfoMapper.updateById(devicePwdInfo);
                    break;
                case 1:
                    log.warn("操作的门锁设备ID:{}已存在重复密码", accessReportDto.getDeviceId());
                   dealHouseKeeperUpdate(devicePwdInfo,accessReportDto);
                    //删除该门锁预置密码,重新获取密码别名
                    break;
                case 2:
                    log.warn("操作的门锁设备ID:{}存储空间已满", accessReportDto.getDeviceId());
                    //删除该门锁密码,修改门锁的密码存储空间
                    break;
                case 3:
                    //修改密码不处理这一操作结果
                    log.warn("操作的门锁设备ID:{}不存在该密码", accessReportDto.getDeviceId());
                    devicePwdInfoMapper.deleteById(devicePwdInfo.getId());
                    break;
                case 4:
                    log.error("设备-门锁:{}修改密码出现未知错误.", accessReportDto.getDeviceId());
                    break;
                default:
                    return;
            }
        }
    }

    /**
     * 处理删除密码回复的权限动态
 e    * @param accessReportDto
     * @throws BusinessException
     */
    private void dealDelPwdAccess(AccessReportDto accessReportDto) throws BusinessException{
        //这里不去使用缓存的机制,耦合太深.从数据库中获取密码记录
        DevicePwdInfo devicePwdInfo = devicePwdInfoMapper.findByDeviceIdAndPwdAlias(accessReportDto);
        if (null == devicePwdInfo) {
            //这里代表门锁的密码信息不对称,去重新获取密码记录
            deviceAccessClient.getAlias(accessReportDto.getDeviceId());
            log.warn("设备-门锁:{}删除密码权限动态无法进行处理", accessReportDto.getDeviceId());
        } else {
            switch (accessReportDto.getOpCode()) {
                case 0:
                    log.info("操作的门锁设备ID:{}操作成功", accessReportDto.getDeviceId());
                    devicePwdInfoMapper.deleteById(devicePwdInfo.getId());
                    break;
                case 1:
                    //删除密码不处理这一操作结果
                    break;
                case 2:
                    //删除密码不处理这一操作结果
                    break;
                case 3:
                    log.warn("操作的门锁设备ID:{}不存在该密码", accessReportDto.getDeviceId());
                    devicePwdInfoMapper.deleteById(devicePwdInfo.getId());
                    break;
                case 4:
                    log.error("操作的门锁设备ID:{}出现未知错误.", accessReportDto.getDeviceId());
                    break;
                default:
                    return;
            }
        }
    }

    /**
     * 处理暂停/恢复密码回复的权限动态
     * @param accessReportDto
     * @throws BusinessException
     */
    private void dealPausePwdAccess(AccessReportDto accessReportDto) throws BusinessException{
        DevicePwdInfo devicePwdInfo = devicePwdInfoMapper.findByDeviceIdAndPwdAlias(accessReportDto);
        if (null == devicePwdInfo){
            //暂停密码/解除暂停密码不处理这里的异常,如果出现,则不是信息不对称,而是云端代码出现的逻辑纰漏.
            throw new BusinessException("设备-门锁:" + accessReportDto.getDeviceId() + "暂停/解除暂停出现未知异常");
        }
        switch (accessReportDto.getOpCode()){
            case 0:
                log.info("操作的门锁设备ID:{}操作成功",accessReportDto.getDeviceId());
                devicePwdInfo.setStatus(accessReportDto.getAction() == 4 ? LockPwdConstant.LOCK_PWD_FREEZED : LockPwdConstant.LOCK_PWD_NORMAL);
                devicePwdInfoMapper.updateById(devicePwdInfo);
                break;
            case 1:
                //暂停密码不处理这一操作结果
                break;
            case 2:
                //暂停密码不处理这一操作结果
                break;
            case 3:
                log.warn("操作的门锁设备ID:{}不存在该密码",accessReportDto.getDeviceId());
                devicePwdInfoMapper.deleteById(devicePwdInfo.getId());
                break;
            case 4:
                log.error("操作的门锁设备ID:{}出现未知错误.",accessReportDto.getDeviceId());
                break;
            default:return;
        }
    }

    private Map<String,String> setPwdAliasMap(String pwdType,String pwdAlias,String pwdId,String listType){
        Map<String,String> devicePwdInfoMap = Maps.newConcurrentMap();
        devicePwdInfoMap.putIfAbsent("pwd_type",pwdType);
        devicePwdInfoMap.putIfAbsent("pwd_alias",pwdAlias);
        devicePwdInfoMap.putIfAbsent("sync_state","1");
        devicePwdInfoMap.putIfAbsent("id",pwdId);
        devicePwdInfoMap.putIfAbsent("list_type",listType);
        return devicePwdInfoMap;
    }

    private void dealHouseKeeperUpdate(DevicePwdInfo devicePwdInfo,AccessReportDto accessReportDto){
        if (accessReportDto.getType() == Integer.parseInt(LockPwdType.LOCK_PWD_ROOMER)){
            if (devicePwdInfo.getOperation_detail_id() != null &&
                    devicePwdInfo.getOperation_detail_id() != 0){
                //有操作记录的门锁,设置status = 1
                OperationDetail operationDetail = operationDetailMapper.selectById(devicePwdInfo.getOperation_detail_id());
                operationDetail.setOperation_result(LockPwdConstant.LOCK_OPERATION_SUCCESS_CODE);
                operationDetail.setErr_reason(LockPwdConstant.LOCK_OPERATION_SUCCESS);
                operationDetailMapper.updateById(operationDetail);
            }
        }
    }
}
